package ar.edu.caece.compiler.grammar.attributes.tree;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import ar.edu.caece.compiler.grammar.attributes.Declaracion;
import ar.edu.caece.compiler.grammar.attributes.DeclaracionVariable;

public class NodeDeclaraciones extends AttributeTreeNode {

	private String labelPadre;
	private List<Declaracion> declaraciones;
	private List<NodeFuncProc> procedimientos;
	private boolean globales;

	public int getCantidadVariablesLocales() {
		int declas = 0;
		for(Declaracion d : declaraciones) {
			if(d.isLocalVariable()) declas++;
		}
		return declas;
	}
	
	public NodeDeclaraciones(List<Declaracion> declaraciones) {
		super();
		this.declaraciones = declaraciones;
	}
	
	public NodeDeclaraciones() {
		globales = false;
		declaraciones = new ArrayList<Declaracion>();
		procedimientos = new ArrayList<NodeFuncProc>();
	}

	public void addDeclaracion(Declaracion declaracion) {
		declaraciones.add(declaracion);
	}
	
	public void addDeclaraciones(Collection<Declaracion> declaraciones) {
		declaraciones.addAll(declaraciones);
	}
	
	public void addProcedimiento(NodeFuncProc procedimiento) {
		procedimientos.add(procedimiento);
	}
	
	public List<Declaracion> getDeclaraciones() {
		return declaraciones;
	}

	public void setDeclaraciones(List<Declaracion> declaraciones) {
		this.declaraciones = declaraciones;
	}

	public void setProcedimientos(List<NodeFuncProc> procedimientos) {
		this.procedimientos = procedimientos;
	}

	public List<NodeFuncProc> getProcedimientos() {
		return procedimientos;
	}
	
	public String toString() {
		StringBuilder builder = new StringBuilder("[Nodo Declaraciones -> Variables/Constantes: ");
		
		for(Declaracion declaracion : declaraciones) {
			builder.append(declaracion);
		}
		builder.append(" Funciones/Procedimientos: " );
		
		for(NodeFuncProc procedimiento : procedimientos) {
			if(!labelPadre.contentEquals(procedimiento.getLabel())) builder.append(procedimiento);
			else builder.append("[procedimiento actual - "+procedimiento.getNombreProc()+"]");
		}
		
		
		return builder.append("]").toString();
	}

	@Override
	public String generateCode() {
		StringBuilder declaracionesBuilder = new StringBuilder();
		if(!isGlobales()) {
			//S�lo deber�a tener declaraciones de variables ac�
			for(NodeFuncProc procedimiento : procedimientos ) {
				declaracionesBuilder.append(procedimiento.generateCode()).append(System.getProperty("line.separator"));
			}	
		}//Si son globales no tengo que hacer nada m�s
		return declaracionesBuilder.toString();
	}
	
	public String generateDeclaration() {
		StringBuilder declaracionesBuilder = new StringBuilder();
		if(isGlobales()) {
			//S�lo deber�a tener declaraciones de variables ac�
			int orden =0;
			for(Declaracion declaracion : declaraciones ) {
				DeclaracionVariable declaVariable = (DeclaracionVariable) declaracion;
				declaracionesBuilder.append("global"+orden)
									.append(" dw ").append( declaVariable.getDimension() )
									.append(" dup(0)")
									.append(System.getProperty("line.separator"));
				orden++;
			}	
		}//Si no son globales no las tengo que escribir. Las tengo que asignar al llamar al procedimiento.
		return declaracionesBuilder.toString();
	}

	public void setGlobales(boolean globales) {
		this.globales = globales;
	}

	public boolean isGlobales() {
		return globales;
	}

	public void setLabelPadre(String labelPadre) {
		this.labelPadre = labelPadre;
	}

	public String getLabelPadre() {
		return labelPadre;
	}

	public int getCantidadParametros() {
		int declas = 0;
		for(Declaracion d : declaraciones) {
			if(d.isParametro()) declas++;
		}
		return declas;
	}

}
